﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace TPL.Xna.Common
{
    /// <summary>
    /// Use simple no-rotation rectangle for collision detection.
    /// </summary>
    public class RectangleSpriteArea : SpriteArea
    {
        /// <summary>
        /// Relative top-left position with parent sprite's image.
        /// </summary>
        public Vector2 TopLeft { get; private set; }

        /// <summary>
        /// Relative bottom-right position with parent sprite's image.
        /// </summary>
        public Vector2 BottomRight { get; private set; }

        /// <summary>
        /// Create with top-left and bottom right corner.
        /// </summary>
        /// <param name="graphicsDevice"></param>
        /// <param name="topLeft"></param>
        /// <param name="bottomRight"></param>
        public RectangleSpriteArea(GraphicsDevice graphicsDevice, Vector2 topLeft, Vector2 bottomRight)
            : base(graphicsDevice)
        {
            TopLeft = topLeft;
            BottomRight = bottomRight;
        }

        /// <summary>
        /// Get current rectangle area.
        /// </summary>
        /// <returns></returns>
        public virtual Rectangle GetCurrentAreaRectangle()
        {
            var cross = BottomRight - TopLeft;
            var root = TopLeft + Shape.Position;
            return new Rectangle((int)root.X, (int)root.Y, (int)cross.X, (int)cross.Y);
        }

        /// <summary>
        /// Create the rectangle shape that is used as sprite area.
        /// </summary>
        /// <param name="graphicsDevice"></param>
        /// <returns></returns>
        protected override ShapeSprite CreateShape(GraphicsDevice graphicsDevice)
        {
            var shape = new ShapeSprite(graphicsDevice).CreateSquare(TopLeft, BottomRight);
            shape.RenderType = RenderType.Line;
            return shape;
        }

        /// <summary>
        /// Whether there is a collision with another area. 
        /// </summary>
        /// <param name="area"></param>
        /// <returns></returns>
        public override bool CollideWith(SpriteArea area)
        {
            if (!(area is RectangleSpriteArea)) throw new NotSupportedException();

            return GetCurrentAreaRectangle().Intersects(
                ((RectangleSpriteArea)area).GetCurrentAreaRectangle());
        }

        /// <summary>
        /// Whether this area is out of the given bound.
        /// </summary>
        /// <param name="bound"></param>
        /// <returns></returns>
        public override bool IsOutOfBound(Rectangle bound)
        {
            return !bound.Contains(GetCurrentAreaRectangle());
        }
    }
}